#include <odb/database.hxx>
#include <odb/mysql/database.hxx>
#include <gflags/gflags.h>
#include <memory>

#include "student.hxx"
#include "student-odb.hxx"

DEFINE_string(host,"127.0.0.1","这是mysql的地址");
DEFINE_int32(port,0,"这是mysql的端口");
DEFINE_string(db,"TestDB","数据库默认的库");
DEFINE_string(user,"root","这是用户名");
DEFINE_string(passward,"123456","这是密码");
DEFINE_string(cset,"utf8","这是mysql客户端字符集");
DEFINE_int32(max_pool,3,"这是mysql连接池最大连接数量");


Student select_student(odb::mysql::database& db)
{
    Student res;
    try
    {
        //开启事务
        odb::mysql::transaction trans(db.begin());
        typedef odb::query<Student> query;
        typedef odb::result<Student> result;

        result ret(db.query<Student>(query::sn == 3));
        if(ret.size() != 1) {
            std::cout << "数量不对" << std::endl;
            return Student();
        }

        res = *ret.begin();
        trans.commit();
    }
    catch(const std::exception& e)
    {
        std::cerr <<" 更新数据失败："  <<e.what() << '\n';
    }
    return res;
}

void insert_classes(odb::mysql::database& db)
{
   try
   {
    //获取事务，开启事务
    odb::transaction trans(db.begin());
    Classes c1("1.1");
    Classes c2("2.2");
    //persist 将对象存储到数据中
    db.persist(c1);
    db.persist(c2);
    //提交事务
    trans.commit();
   }
   catch(const std::exception& e)
   {
    std::cout << "插入数据失败：" << e.what() << std::endl; 
   } 
}

void insert_student(odb::mysql::database& db)
{
    try
    {
        odb::transaction trans(db.begin());
        Student s1(1,"张三",16,1); 
        Student s2(2,"李四",17,1);
        Student s3(3,"王五",18,1);
        Student s4(4,"赵六",19,2);
        db.persist(s1);
        db.persist(s2);
        db.persist(s3);
        db.persist(s4);
        trans.commit();
    }catch(const std::exception& e) {
        std::cout << "插入数据失败：" << e.what() << std::endl;
    }
}

void update_student(odb::mysql::database& db,Student& stu) 
{
    try
    {
        odb::mysql::transaction trans(db.begin());
        db.update(stu);
        trans.commit();
    
    }catch(const std::exception& e) 
    {
        std::cout << "插入数据失败：" << e.what() << std::endl; 
    }
}

void remove_student(odb::mysql::database& db)
{
    try
    {
        odb::transaction trans(db.begin());
        typedef odb::query<Student> query;
        db.erase_query<Student>(query::class_id == 2);
        trans.commit();
    }catch(const std::exception& e) {
        std::cout << "删除数据失败：" << e.what() << std::endl;  
    }
}

void classes_student(odb::mysql::database& db)
{
    try
    {
        odb::transaction trans(db.begin());
        typedef odb::query<struct classes_student> query;
        typedef odb::result<struct classes_student> result;
        result ret(db.query<struct classes_student>(query::classes::id == 1));
        for(auto it = ret.begin(); it != ret.end(); it++) {
            std::cout << it->id << std::endl;
            std::cout << it->sn << std::endl;
            std::cout << it->name << std::endl;
            if(it->age) std::cout << *it->age << std::endl;
            std::cout << it->classes_name << std::endl;
        }
        trans.commit();
    }catch(const std::exception& e)
    {
        std::cout << "查询数据失败：" << e.what() << std::endl;  
    }
}

void all_student(odb::mysql::database& db)
{
    try
    {
        odb::transaction trans(db.begin());
        typedef odb::query<Student> query;
        typedef odb::result<struct all_name> result;
        result ret(db.query<struct all_name>(query::id == 1));
        for(auto it = ret.begin(); it != ret.end(); it++) {
            std::cout << it->name << std::endl;
        }
        trans.commit();
    }catch(const std::exception& e)
    {
        std::cout << "查询数据失败：" << e.what() << std::endl;  
    }
}

int main(int argc,char* argv[]) 
{
    google::ParseCommandLineFlags(&argc,&argv,true);
    // 构造连接池工厂函数
    std::unique_ptr<odb::mysql::connection_pool_factory> cpf(
         new odb::mysql::connection_pool_factory(FLAGS_max_pool, 0));
    // 构造数据库操作对象
    odb::mysql::database db(FLAGS_user,FLAGS_passward,FLAGS_db,FLAGS_host,FLAGS_port,"",FLAGS_cset,0,std::move(cpf));
    // 数据操作
    //insert_classes(db);
//    insert_student(db); 

//    auto stu = select_student(db);
//    std::cout << stu.sn() << std::endl;
//    std::cout << stu.name() << std::endl;
//    std::cout << *stu.age() << std::endl;
//    std::cout << stu.class_id() << std::endl;
//
//    stu.set_age(23);
//    //update_student(db,stu);

//     remove_student(db);
//    classes_student(db);

    all_student(db);

    return 0;
}